home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / glass / glass.lha / GLASS / glammar / gg02.c < prev    next >
C/C++ Source or Header  |  1991-01-21  |  42KB  |  1,819 lines

  1. /*
  2.  
  3.     This file is a part of the GLAMMAR source distribution 
  4.     and therefore subjected to the copy notice below. 
  5.     
  6.     Copyright (C) 1989,1990  Eric Voss, ericv@cs.kun.nl 
  7.  
  8.     This program is free software; you can redistribute it and/or modify
  9.     it under the terms of the GNU General Public License as published by
  10.     the Free Software Foundation version 1
  11.  
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21. /* file  abstract syntax tree    */
  22. #include "gg1.h"
  23. #include "gg2.h"
  24.  
  25. int             optlefthsd = 0, dfa, last_lattice = nil,
  26.                 firstnode = nil;
  27.                 
  28. compile()
  29. {
  30.    int             rule;
  31.    initialize();
  32.    grammar();
  33.    if (root == nil)
  34.       root = laststdpred;
  35.    if ((syntaxerrors > 0))
  36.       exit(syntaxerrors);
  37.    if (index_flag) 
  38.       fclose (indexfile);
  39.    init_builtins();
  40.    meta2init(); 
  41.    list();
  42.  
  43.    if (verbose_flag)
  44.       fprintf(stderr,
  45.         "no syntax errors detected.\
  46.         \n%d name entries in hash table (max = %d).\
  47.         \n%d chars in symbol table.\
  48.         \n%d name clashes occured.\
  49.         \nsetting meta affixes.\n",
  50.               nr_names, maxnt,symbol_table_size+charindex, name_clashes);
  51.    set_meta_affixes();
  52.    if (verbose_flag)
  53.       fprintf(stderr,
  54.               "match applications with definitions.\n");
  55.    
  56.    linktodefs();
  57.  
  58.   if (parse_tree_flag ) {
  59.       parse_tree();
  60.       printtree();
  61.       exit(0);
  62.    }
  63.  
  64.   if (id_tree_flag ) {
  65.       id_tree();
  66.       printtree();
  67.       exit(0);
  68.    }
  69.  
  70.   if (cfg_flag ) {
  71.       print_cfg_tree();
  72.       exit(0);
  73.    }
  74.  
  75.    if (verbose_flag)
  76.       fprintf(stderr, "eliminate defining expressions.\n");
  77.  
  78.    eag();
  79.  
  80.    tr_lattice();
  81.    if (verbose_flag)
  82.       fprintf(stderr,
  83.               "eliminate implied equals.\n");
  84.    ie();
  85.  
  86.    if (verbose_flag)
  87.       fprintf(stderr, "eliminate wheres.\n");
  88.  
  89.    wheres();
  90.  
  91.    if (verbose_flag)
  92.       fprintf(stderr, "check metagrammar.\n");
  93.    check_metagrammar();
  94.  
  95.  
  96.    if (fulltrace_flag || fullstat_flag) {
  97.        if (verbose_flag)
  98.            fprintf(stderr, "alias builtin for tracing.\n");
  99.        trace();
  100.    }
  101.  
  102.  
  103.    if (lift_flag && memo_flag) {
  104.          if (verbose_flag)
  105.             fprintf(stderr, "compute empty rules.\n"); 
  106.          empty();
  107.        
  108.          if (memopt_flag) { 
  109.             if (verbose_flag)
  110.                fprintf(stderr, "memoizer optimizer.\n"); 
  111.             memopt();
  112.          }
  113.          if (verbose_flag)
  114.             fprintf(stderr, "compute  recursive  rules.\n"); 
  115.          recursive_();
  116.          if (verbose_flag)
  117.             fprintf(stderr, "check on left recursive rules.\n"); 
  118.          left_rec();
  119.    }
  120.  
  121.  
  122.    if (startname == NULL)
  123.       startnode = root;
  124.    else
  125.       for (rule = root; rule != nil; rule = BROTHER(rule))
  126.          if (REPR(rule) == startname) {
  127.             startnode = rule;
  128.             break;
  129.          }
  130.    if (rule == nil) {
  131.       fprintf(stderr, "STARTRULE `%s' not found and set to %s\n",
  132.  
  133.               startname, REPR(root));
  134.       startnode = root;
  135.    }
  136.    determ();
  137.    if (memo_flag)  {
  138.      if (verbose_flag)
  139.       fprintf(stderr, "set affix directed parsing affixes ; do a memo walk\n");
  140.       adp_walk();
  141.    } 
  142.    if (verbose_flag)
  143.       fprintf(stderr, "compute affix usage.\n");
  144.    affixuse();
  145.    if (tree_flag) {
  146.       printtree();
  147.       exit(0);
  148.    }
  149.    if ((memo_flag)  && (MARKED(skip,deterministic))) {
  150.       fprintf(stderr, "compiler error: skip deterministic?\n");
  151.       exit(-1);
  152.    }
  153.    if (verbose_flag)
  154.       fprintf(stderr, "code generation phase\n");
  155.    if(separate_comp_flag)
  156.       compile_parts();
  157.    else 
  158.      code();
  159. }
  160.  
  161. initialize()
  162. {
  163.    lastmetarule = nil;
  164.    first_lattice = nil;
  165.    reccount = 0;
  166.    astindex = 0;
  167.    brother = 0;
  168.    charindex = 0;
  169.    prevcharindex = 0;
  170.    chartable[0] = '\0';
  171.    hashindex = 0;
  172.    NtCount = 0;
  173.    RuleCount = 0;
  174.    nrterms = 0;
  175.    nrntmems = 0;
  176.    syntaxerrors = 0;
  177.    usefullerrmsg = true;
  178.    startname = NULL;
  179.    initnametable();
  180.    stddefs();
  181.    underscore_allowed = false;
  182.    laststdmetarule = lastmetarule;
  183. }
  184.  
  185. newnode(name, brothers, sons, repr)
  186.    int             name, brothers, sons;
  187.    char           *repr;
  188. {
  189.    NODENAME(astindex) = name;
  190.    BROTHER(astindex) = brothers;
  191.    SON(astindex) = sons;
  192.    DEF(astindex) = -1;
  193.    REPR(astindex) = repr;
  194.    brother = astindex++;
  195.    if (astindex >=  max_item) 
  196.       realloc_ast();
  197. }
  198.  
  199. newdefnode(name, brothers, sons, def, repr)
  200.    int             name, brothers, sons, def;
  201.    char           *repr;
  202. {
  203.    NODENAME(astindex) = name;
  204.    BROTHER(astindex) = brothers;
  205.    SON(astindex) = sons;
  206.    DEF(astindex) = def;
  207.    REPR(astindex) = repr;
  208.    brother = astindex++;
  209.    if (astindex >= max_item) 
  210.       realloc_ast();
  211. }
  212.  
  213. newrulenode(name, brothers, sons, def, repr)
  214.    int             name, brothers, sons, def;
  215.    char           *repr;
  216. {
  217.    NODENAME(astindex) = name;
  218.    BROTHER(astindex) = brothers;
  219.    SON(astindex) = sons;
  220.    DEF(astindex) = def;
  221.    REPR(astindex) = repr;
  222.    brother = astindex++;
  223.    astindex++;
  224.    if (astindex >= max_item) 
  225.       realloc_ast();
  226. }
  227. realloc_ast() {
  228.   max_item <<= 1; 
  229.   ast = (AST *) realloc(ast,(max_item + 2) * sizeof(AST));
  230.   if (ast == NULL) {
  231.    fprintf(stderr,"glammar fatal msg: no %d bytes available for heap space\n",
  232.        max_item*20);
  233.    exit(1);
  234.   }
  235.   if (verbose_flag) 
  236.    fprintf(stderr,"realloc ast: %d bytes available for heap space\n",
  237.        max_item*20);
  238. }
  239.  
  240. grammar()
  241. {
  242.    brother = nil;
  243.    pieces();
  244.    if (!feof(input))
  245.       errmsg("RULES");
  246. }
  247.  
  248. char * cur_part_name;
  249. char * part_file;
  250.  
  251. static int part_name_match = false;
  252. pieces()
  253. {
  254.    char inputfilename [256];
  255.    if (input_from_partlist) {
  256.       (void) sprintf(&chartable[charindex], "%s.p\0", thispart);
  257.       part_file = &chartable[charindex];
  258.       while (chartable[charindex++] != '\0') ;
  259.       prevcharindex = charindex;
  260.       partlist = fopen(part_file, "r");
  261.       if (partlist == NULL) {
  262.          fprintf(stderr ,"glammar: %s: No such file\n", part_file);
  263.          exit(24);
  264.       }
  265.    }
  266.    sum =0;
  267.    if (input_from_partlist && (fscanf(partlist, "%s %d", thispart,&sum) != -1)) {
  268.       int comp = false;
  269.       cur_part_name = &chartable[charindex];
  270.       strcpy(cur_part_name,thispart);
  271.       while (chartable[charindex++] != '\0') ;
  272.       prevcharindex = charindex;
  273.       input = fopen(thispart, "r");
  274.       addpart();
  275.       if (input == NULL) {
  276.          fprintf(stderr, "glammar: %s: No such file\n", thispart);
  277.          exit(24);
  278.       }
  279.       line =1;
  280.       getfirstchar();
  281.       brother = nil;
  282.       
  283.       rules(rnode);
  284.       getlastnode();
  285.       if (lastnode <= laststdpred) {
  286.          fprintf(stderr, "In %s: HYPERrules expected.\n",
  287.               cur_part_name);
  288.         syntaxerrors += 1;
  289.       }
  290.       if (verbose_flag)
  291.          fprintf(stderr, "glammar: %s linked to %s\n", REPR(lastnode),
  292.                  REPR(laststdpred));
  293.       root = brother;
  294.       DEF(root) = (int) cur_part_name;
  295.       OLDSUM(root) = sum; 
  296.       brother = nil;
  297.       morepieces();
  298.       getlastnode();
  299.       BROTHER(lastnode) = laststdpred;
  300.    } else if (!input_from_partlist) {
  301.       if (!input_from_stdin) {
  302.          (void) sprintf(inputfilename, "%s.g\0", thispart);
  303.  
  304.          input = fopen(inputfilename, "r");
  305.          if (verbose_flag)
  306.             fprintf(stderr, "%s opened\n", inputfilename);
  307.       } else {
  308.          input = stdin;
  309.          (void) sprintf(inputfilename, "@stdin@");
  310.          if (verbose_flag)
  311.             fprintf(stderr, "stdin opened\n");
  312.       }
  313.  
  314.       if (input == NULL) {
  315.          fprintf(stderr,
  316.          "Glammar: (compiler error) cannot open single file '%s'\n");
  317.          exit(12);
  318.       }
  319.       line = 1;
  320.       getfirstchar();
  321.       brother = nil;
  322.       rules(rnode+docompile);
  323.       root = brother;
  324.       if (root != nil)  {
  325.           getlastnode();
  326.           BROTHER(lastnode) = laststdpred;
  327.       }
  328.       else  {
  329.          if (verbose_flag)
  330.            fprintf(stderr, "Glammar: empty file?\n");
  331.       }
  332.    } else {
  333.       fprintf(stderr, "Glammar: specified partlist empty? Bye.\n");
  334.       exit(12);
  335.    }
  336. }
  337.  
  338.  
  339. morepieces()
  340. {
  341.    int             prevlastnode;
  342.    sum = 0;
  343.    if (fscanf(partlist, "%s %d", thispart,&sum) != -1) {
  344.       int comp = false;
  345.       fclose(input);
  346.       input = fopen(thispart, "r");
  347.       cur_part_name = &chartable[charindex];
  348.       strcpy(cur_part_name,thispart);
  349.       while (chartable[charindex++] != '\0') ;
  350.       prevcharindex = charindex;
  351.       addpart();
  352.       if (input == NULL) {
  353.          fprintf(stderr, "Glammar: cannot open file: `%s' \n",
  354.                  thispart);
  355.          exit(24);
  356.       }
  357.       line = 1;
  358.       getnextchar();
  359.       prevlastnode = lastnode;
  360.       brother = nil;
  361.       comp = false;
  362.       rules(rnode);
  363.       getlastnode();
  364.       if (prevlastnode != lastnode) {
  365.          if (verbose_flag)
  366.             fprintf(stderr, "glammar: %s linked to %s\n",
  367.                     REPR(prevlastnode),
  368.                     REPR(firstnode));
  369.          DEF(firstnode) = (int) cur_part_name;
  370.          OLDSUM(firstnode) = (int) sum;
  371.          BROTHER(prevlastnode) = firstnode;
  372.       } else {
  373.          fprintf(stderr, "In %s: HYPERrules expected.\n",
  374.               cur_part_name);
  375.         syntaxerrors += 1;
  376.       }
  377.       morepieces();
  378.    }
  379. }
  380.  
  381. getlastnode()
  382. {
  383.    int             rule;
  384.    for (rule = firstnode; rule != nil; rule = BROTHER(rule)) {
  385.       if (NODENAME(rule) != meta_prod_rule) 
  386.          if (NODENAME(rule) != 0)
  387.            lastnode = rule;
  388.    }
  389. }
  390.  
  391. rules(ruletype)
  392.    int             ruletype;
  393. {
  394.    int             sons, ln,loc_glob;
  395.    char           *thisname = "??";
  396.    
  397. l:
  398.    if (feof(input)) {
  399.       return;
  400.    }
  401.    ln = line;
  402.    if (name_display_mix()) {
  403.       thisname = ntname;
  404.       if (define_symbol(&loc_glob)) ;
  405.  
  406.       else if (startspecification())
  407.          goto l;
  408.  
  409.       else {
  410.          errmsg("DEFINE [: =] symbol");
  411.          skiptopoint_symbol();
  412.          rules(rnode);
  413.          usefullerrmsg = false;
  414.       }
  415.    } else {
  416.       errmsg("LEFT HANDSIDE");
  417.       rulename = "??";
  418.       skiptopoint_symbol();
  419.       rules(rnode);
  420.       usefullerrmsg = false;
  421.    }
  422.  
  423.    brother = nil;
  424.    rulename = thisname;
  425.    if (metarule(ruletype)) 
  426.       goto l;
  427.    else {
  428.       if (index_flag) {
  429.          if (fprintf(indexfile, "%s (", thisname) == EOF)
  430.                 fprintf(stderr,"glammar: Write to index file failed\n");
  431.          printaffixtype(indexfile, lastaffixtree);
  432.          if (input_from_partlist)
  433.             fprintf(indexfile, "), file: `%s' %d\n", thispart, line);
  434.          else
  435.             fprintf(indexfile, "), %d\n", line);
  436.       }
  437.       alts(true);
  438.       sons = brother;
  439.       brother = nil;
  440.       rules(ruletype);
  441.       if (input_from_partlist)
  442.       newrulenode(ruletype | loc_glob, brother, sons, cur_part_name ,thisname);
  443.       else newrulenode(ruletype | loc_glob, brother, sons, ln ,thisname);
  444.       firstnode = brother;
  445.       NtCount += 1;
  446.    }
  447. }
  448.  
  449.  
  450. alts(firstalt)
  451.    int             firstalt;
  452. {
  453.    int             asons,
  454.                    lefths,
  455.                    errline,
  456.                    locaffixtree,
  457.                    memaffixtree,
  458.                    settype;
  459.    char           *thisname = "LHS";
  460.    int             lkh = 0;
  461.    lefths = false;
  462.    asons = nil;
  463.    errline = line;
  464.    setlookahead(&lkh);
  465.    if (firstalt) {
  466.       defaffixtree = lastaffixtree;
  467.       dfa = defaffixtree;
  468.    }
  469.    locaffixtree = defaffixtree;
  470.    if ((name_display_mix()) || (cut_symbol())) { int l_g;
  471.       thisname = ntname;
  472.       if (define_symbol(&l_g)) {
  473.          lefths = true;
  474.          if (firstalt)
  475.             errmsg("only one left-hand side");
  476.          locaffixtree = lastaffixtree;
  477.          defaffixtree = locaffixtree;
  478.          brother = nil;
  479.          if (lkh == lookahead)
  480.             errmsg("no LOOKAHEAD symbol");
  481.          members();
  482.       } else if (!comma_symbol()) {
  483.          newnode(ntnode | lkh, nil, brother, thisname);
  484.          nrntmems += 1;
  485.       } else {
  486.          memaffixtree = brother;
  487.          brother = nil;
  488.          members();
  489.          newnode(ntnode | lkh, brother, memaffixtree, thisname);
  490.          nrntmems += 1;
  491.       }
  492.    } else if (terminal()) {
  493.       if (!comma_symbol()) {
  494.          if (strlen(string) == 0);
  495.          else {
  496.             newnode(tnode | lkh, nil, nil, string);
  497.             nrterms += 1;
  498.          }
  499.       } else {
  500.          thisname = string;
  501.          members();
  502.          if (strlen(thisname) == 0);
  503.          else {
  504.             newnode(tnode | lkh, brother, nil, thisname);
  505.             nrterms += 1;
  506.          }
  507.       }
  508.    } else if (set()) {
  509.       thisname = string;
  510.       if (!display())  {
  511.            newnode(affixnt, nil, nil, dont_care);
  512.            newnode(derived, nil, brother, "(nil)");
  513.            lastaffixtree = brother;
  514.       }
  515.       else if ((NODENAME(brother) != derived) || (BROTHER(brother) != nil))
  516.          errmsg("ONE DERIVED AFFIX");
  517.  
  518.       if (!comma_symbol()) {
  519.          newnode(cnode | lastsettype | lkh, nil, brother, thisname);
  520.          nrterms += 1;
  521.       } else {
  522.          memaffixtree = brother;
  523.          settype = lastsettype;
  524.          members();
  525.          newnode(cnode | settype | lkh, brother, memaffixtree, thisname);
  526.          nrterms += 1;
  527.       }
  528.    }
  529.    if ((!lefths) && (optlefthsd == 0) && (!firstalt)) {
  530.       optlefthsd = 1;
  531.       if (input_from_partlist)
  532.           fprintf(stderr, "In %s:\n", cur_part_name);
  533.       fprintf(stderr, "line %d: (message) no left-hand side in `%s'\n",
  534.               errline, rulename);
  535.    }
  536.    asons = brother;
  537.    brother = nil;
  538.    if ((!lefths) && (!firstalt))  {
  539.          copy_display();
  540.          locaffixtree = brother;
  541.    }
  542.    brother = nil;
  543.    if (goon_symbol()) {
  544.       alts(false);
  545.       newnode(locaffixtree, brother, asons, (char *) errline);
  546.       RuleCount += 1;
  547.       if (lefths) {
  548.          if (rulename != thisname) {
  549.       if (input_from_partlist)
  550.           fprintf(stderr, "In %s:\n", cur_part_name);
  551.             fprintf(stderr, "line %d : LHS '%s' expected\n",
  552.                     errline, rulename);
  553.             syntaxerrors += 1;
  554.             rulename = thisname;
  555.             dfa = locaffixtree;
  556.          } else if (!consistentaffixtype(dfa, locaffixtree)) {
  557.       if (input_from_partlist)
  558.           fprintf(stderr, "In %s:\n", cur_part_name);
  559.             fprintf(stderr, "line %d : LHS '%s' :",
  560.                     errline, rulename);
  561.             affixerrmsg(locaffixtree, dfa);
  562.             syntaxerrors += 1;
  563.          }
  564.       }
  565.    } else if (point_symbol()) {
  566.       newnode(locaffixtree, brother, asons, (char *) errline);
  567.       RuleCount += 1;
  568.       if (lefths) {
  569.          if (rulename != thisname) {
  570.       if (input_from_partlist)
  571.           fprintf(stderr, "In %s:\n", cur_part_name);
  572.             fprintf(stderr, "line %d : LHS '%s' expected\n",
  573.                     errline, rulename);
  574.             rulename = thisname;
  575.             dfa = locaffixtree;
  576.             syntaxerrors += 1;
  577.          } else if (!consistentaffixtype(dfa, locaffixtree)) {
  578.       if (input_from_partlist)
  579.           fprintf(stderr, "In %s:\n", cur_part_name);
  580.             fprintf(stderr, "line %d : LHS '%s' :",
  581.                     errline, rulename);
  582.             affixerrmsg(locaffixtree, dfa);
  583.             syntaxerrors += 1;
  584.          }
  585.       }
  586.    } else {
  587.       errmsg("MEMBERS");
  588.       skiptopoint_symbol();
  589.       rules(rnode);
  590.       usefullerrmsg = false;
  591.    }
  592. }
  593.  
  594.  
  595. #define LOOKahead_symbol ( thischar == '?' )
  596.  
  597. setlookahead(lkh)
  598.    int            *lkh;
  599. {
  600.    if (LOOKahead_symbol) {
  601.       *lkh = lookahead;
  602.       getnextchar();
  603.    }
  604. }
  605.  
  606.  
  607. members()
  608. {
  609.    char           *repr;
  610.    int             locaffixtree,
  611.                    settype,
  612.                    lkh = 0;
  613.    setlookahead(&lkh);
  614.    if (terminal()) {
  615.       if (!comma_symbol()) {
  616.          if (strlen(string) == 0);
  617.          else {
  618.             newnode(tnode + lkh, nil, nil, string);
  619.             nrterms += 1;
  620.          }
  621.       } else {
  622.          repr = string;
  623.          members();
  624.          if (strlen(repr) == 0);
  625.          else {
  626.             newnode(tnode + lkh, brother, nil, repr);
  627.             nrterms += 1;
  628.          }
  629.       }
  630.    } else if (set()) {
  631.       repr = string;
  632.       if (!display()) {
  633.            newnode(affixnt, nil, nil, dont_care);
  634.            newnode(derived, nil, brother, "(nil)");
  635.            lastaffixtree = brother;
  636.       } else if ((NODENAME(brother) != derived) || (BROTHER(brother) !=
  637.                                                   nil))
  638.          errmsg("ONE DERIVED AFFIX");
  639.       if (!comma_symbol()) {
  640.          newnode(cnode | lastsettype | lkh, nil, brother, repr);
  641.          nrterms += 1;
  642.       } else {
  643.          settype = lastsettype;
  644.          locaffixtree = brother;
  645.          members();
  646.          newnode(cnode | settype | lkh, brother, locaffixtree, repr);
  647.          nrterms += 1;
  648.       }
  649.    } else if ((name_display_mix()) || (cut_symbol())) {
  650.       repr = ntname;
  651.       if (!comma_symbol()) {
  652.          newnode(ntnode | lkh, nil, brother, repr);
  653.          nrntmems += 1;
  654.       } else {
  655.          locaffixtree = lastaffixtree;
  656.          members();
  657.          newnode(ntnode | lkh, brother, locaffixtree, repr);
  658.          nrntmems += 1;
  659.       }
  660.    }
  661. }
  662.  
  663.  
  664. #define GETnextchar thischar = getc(input)
  665. #define SKIPset_symbol thischar = getc(input)
  666.  
  667. set()
  668. {
  669.    lastsettype = 0;
  670.    if (complement_symbol()) {
  671.       if (charindex > maxchars - 256)
  672.           alloc_chartable();
  673.       lastsettype = complset;
  674.       if (thischar != '{' && thischar != '!') {
  675.          errmsg("SET");
  676.          skiptopoint_symbol();
  677.          rules(rnode);
  678.          usefullerrmsg = false;
  679.       } else if (thischar == '!')
  680.          lastsettype |= morelongset();
  681.  
  682.       else {
  683.          errmsg("!");
  684.          lastsettype |= moreset();
  685.       }
  686.    } else {
  687.       if (thischar != '{' && thischar != '!')
  688.          return false;
  689.       if (charindex > maxchars - 256)
  690.           alloc_chartable();
  691.       if (thischar == '!')
  692.          lastsettype |= morelongset();
  693.       else {
  694.          errmsg("!");
  695.          lastsettype |= moreset();
  696.       }
  697.    }
  698.    lastsettype |= sequenceroption();
  699.    return true;
  700. }
  701.  
  702.  
  703. morelongset()
  704. {
  705.    SKIPset_symbol;
  706.    while (thischar != '!') {
  707.       if (thischar == '"')
  708.          chartable[charindex++] = '\\';
  709.       else if (thischar == '\\') {
  710.          GETnextchar;
  711.          switch (thischar) {
  712.          case '\n': 
  713.             GETnextchar; line +=1;
  714.             continue;
  715.          case '"': 
  716.             chartable[charindex++] = '\\';
  717.             chartable[charindex++] = '\\';
  718.          case '0': 
  719.          case 'r': 
  720.          case 't': 
  721.          case 'n': 
  722.          case 'f': 
  723.          case 'a': 
  724.          case '\\': 
  725.             chartable[charindex++] = '\\';
  726.             break;
  727.          case '!': 
  728.             break;
  729.          default: 
  730.             chartable[charindex++] = '\\';
  731.             chartable[charindex++] = '\\';
  732.             break;
  733.          }
  734.       }
  735.       chartable[charindex++] = thischar;
  736.       GETnextchar;
  737.       if (thischar == '\n') {
  738.          errmsg("not a NEW LINE char in a string");
  739.          return longset;
  740.       }
  741.    }
  742.    SKIPset_symbol;
  743.    string = &chartable[prevcharindex];
  744.    chartable[charindex++] = '\0';
  745.    prevcharindex = charindex;
  746.    return longset;
  747. }
  748.  
  749.  
  750. moreset()
  751. {
  752.    do {
  753.       SKIPset_symbol;
  754.       while (thischar != '}') {
  755.          chartable[charindex++] = thischar;
  756.          GETnextchar;
  757.          if (thischar == '\n') {
  758.             errmsg("not a NEW LINE char in a set");
  759.             line += 1;
  760.             break;
  761.          }
  762.       }
  763.  
  764.       SKIPset_symbol;
  765.       if (thischar == '}')
  766.          chartable[charindex++] = thischar;
  767.  
  768.    } while (thischar == '}');
  769.    string = &chartable[prevcharindex];
  770.    chartable[charindex++] = '\0';
  771.    prevcharindex = charindex;
  772.    return nset;
  773. }
  774.  
  775.  
  776. sequenceroption()
  777. {
  778.    skiplayout();
  779.    if (thischar == '*') {
  780.       getnextchar();
  781.       return starset;
  782.    }
  783.    if (thischar == '+') {
  784.       getnextchar();
  785.       return plusset;
  786.    }
  787.    if (thischar == ')') {
  788.       getnextchar();
  789.       return 0;
  790.    }
  791.    return 0;
  792. }
  793.  
  794.  
  795. #define QUOTE thischar == '"'
  796. #define NotQUOTE thischar != '"'
  797. #define GETnextTerminal thischar = getc(input)
  798. #define SKIPquote thischar = getc(input)
  799.  
  800. terminal()
  801. {
  802.    if (QUOTE) {
  803.       if (charindex > maxchars - 256)
  804.           alloc_chartable();
  805.       SKIPquote;
  806.       mterminal();
  807.       return true;
  808.    }
  809.    return false;
  810. }
  811.  
  812.  
  813. mterminal()
  814. {
  815.    while (NotQUOTE) {
  816.       if (thischar == '\\') {
  817.          GETnextchar;
  818.          switch (thischar) {
  819.          case '\n': 
  820.          case '\f': 
  821.          case '\r': 
  822.             GETnextchar;
  823.             line +=1;
  824.             continue;
  825.          case '"': 
  826.          case '0': 
  827.          case 'r': 
  828.          case 't': 
  829.          case 'n': 
  830.          case 'f': 
  831.          case 'a': 
  832.          case '\\': 
  833.             chartable[charindex++] = '\\';
  834.             break;
  835.          default: 
  836.             chartable[charindex++] = '\\';
  837.             chartable[charindex++] = '\\';
  838.             break;
  839.          }
  840.       }
  841.       chartable[charindex++] = thischar;
  842.       GETnextchar;
  843.       if (thischar == '\n') {
  844.          errmsg("not a NEW LINE char in a string");
  845.          return ;
  846.       }
  847.    }
  848.    SKIPquote;
  849.    string = &chartable[prevcharindex];
  850.    chartable[charindex++] = '\0';
  851.    prevcharindex = charindex;
  852.    skiplayout();
  853. }
  854. cut_symbol()
  855. {
  856.    if (thischar == '-') {
  857.       getnextchar();
  858.       if (thischar == '>')
  859.          getnextchar();
  860.  
  861.       else
  862.          errmsg("SLASH symbol");
  863.  
  864.       string = REPR(cut);
  865.       ntname = string;
  866.       lastaffixtree = nil;
  867.       brother = nil;
  868.       return true;
  869.    } else
  870.       return false;
  871. }
  872.  
  873.  
  874. comma_symbol()
  875. {
  876.    if (thischar == ',') {
  877.       getnextchar();
  878.       return true;
  879.    } else
  880.       return false;
  881. }
  882.  
  883. mint_symbol()
  884. {
  885.    return (isdigit( thischar) );
  886. }
  887.  
  888. super_symbol()
  889. {
  890.    if (thischar == '@') {
  891.       getnextchar();
  892.       return true;
  893.    } else
  894.       return false;
  895. }
  896.  
  897. lattice_symbol()
  898. {
  899.    if (thischar == '{') {
  900.       getnextchar();
  901.       getnextchar();
  902.       return true;
  903.    } else
  904.       return false;
  905. }
  906.  
  907. define_symbol(l_g)   /* local or global rule */
  908. int * l_g;
  909. {
  910.    if (thischar == '=' ) {
  911.       *l_g = external;
  912.       getnextchar();
  913.       return true;
  914.    } else if (thischar == ':' ) {
  915.       if (all_external_flag)
  916.         *l_g = external;
  917.       else  *l_g = rnode;
  918.       *l_g = external;  /* always external */
  919.       getnextchar();
  920.       return true;
  921.    } else
  922.       return false;
  923. }
  924.  
  925.  
  926. start_symbol()
  927. {
  928.    if (thischar == '!') {
  929.       getnextchar();
  930.       return true;
  931.    } else
  932.       return false;
  933. }
  934.  
  935.  
  936. point_symbol()
  937. {
  938.    if (thischar == '.') {
  939.       getnextchar();
  940.       return true;
  941.    } else
  942.       return false;
  943. }
  944.  
  945.  
  946. dontcare_symbol()
  947. {
  948.    if (thischar == '_') {
  949.       getnextchar();
  950.       return true;
  951.    } else
  952.       return false;
  953. }
  954.  
  955. fact_symbol()
  956. {
  957.    if (thischar == '*') {
  958.       getnextchar();
  959.       return true;
  960.    } else if ((isalpha(thischar)) ||  (thischar == '"')) {
  961.       if (input_from_partlist)
  962.           fprintf(stderr, "In %s:\n", cur_part_name);
  963.       fprintf (stderr,"line %d: * symbol inserted\n",line);
  964.       return true;
  965.    } else
  966.       return false;
  967. }
  968.  
  969. negate_symbol()
  970. {
  971.    if (thischar == '-') {
  972.       getnextchar();
  973.       return true;
  974.    }
  975.    return false;
  976. }
  977.  
  978. pos_symbol()
  979. {
  980.    if (thischar == '+') {
  981.       getnextchar();
  982.       return true;
  983.    }
  984.    return false;
  985. }
  986.  
  987. plus_symbol()
  988. {
  989.    if (thischar == '+') {
  990.       getnextchar();
  991.       return true;
  992.    } else if ((isalpha(thischar)) ||  (thischar == '"')) {
  993.       if (input_from_partlist)
  994.           fprintf(stderr, "In %s:\n", cur_part_name);
  995.       fprintf (stderr,"line %d: + symbol inserted\n",line);
  996.       return true;
  997.    } else  
  998.       return false;
  999. }
  1000.  
  1001.  
  1002. close_symbol()
  1003. {
  1004.    if (thischar == ')') {
  1005.       getnextchar();
  1006.       return true;
  1007.    } else
  1008.       return false;
  1009. }
  1010.  
  1011.  
  1012. open_symbol()
  1013. {
  1014.    if (thischar == '(') {
  1015.       getnextchar();
  1016.       return true;
  1017.    } else
  1018.       return false;
  1019. }
  1020.  
  1021.  
  1022. complement_symbol()
  1023. {
  1024.    if (thischar == '^' || thischar == '~') {
  1025.       getnextchar();
  1026.       return true;
  1027.    } else
  1028.       return false;
  1029. }
  1030.  
  1031.  
  1032. flow_symbol()
  1033. {
  1034.    if (thischar == '>') {
  1035.       getnextchar();
  1036.       return true;
  1037.    } else
  1038.       return false;
  1039. }
  1040.  
  1041.  
  1042. goon_symbol()
  1043. {
  1044.    if (thischar == ';') {
  1045.       getnextchar();
  1046.       return true;
  1047.    } else
  1048.       return false;
  1049. }
  1050.  
  1051. getfirstchar()
  1052. {
  1053.    thischar = getc(input);
  1054.    glm_options();
  1055. }
  1056.  
  1057. getnextchar()
  1058. {
  1059.    thischar = getc(input);
  1060.    skiplayout();
  1061. }
  1062.  
  1063.  
  1064. skiplayout()
  1065. {
  1066.    while ((thischar == '\t' || thischar == ' ' || thischar ==
  1067.            '\n') &&
  1068.           (!feof(input))) {
  1069.       if (thischar == '\n')
  1070.          line += 1;
  1071.       thischar = getc(input);
  1072.    }
  1073.  
  1074.    if (thischar == '#') {
  1075.       do {
  1076.          thischar = getc(input);
  1077.       } while ((thischar != '#' && thischar != '\n') && (!feof(input)));
  1078.  
  1079.       skiplayout();
  1080.    }
  1081.    if (thischar == '%') {
  1082.       do {
  1083.          thischar = getc(input);
  1084.          if (thischar == '\n')
  1085.             line += 1;
  1086.  
  1087.       } while ((thischar != '%') && (!feof(input)));
  1088.  
  1089.       getnextchar();
  1090.    }
  1091. }
  1092.  
  1093.  
  1094. displayoption()
  1095. {
  1096.    if (display())
  1097.       lastaffixtree = brother;
  1098.    else {
  1099.       lastaffixtree = nil;
  1100.       brother = nil;
  1101.    }
  1102. }
  1103.  
  1104.  
  1105. display()
  1106. {
  1107.    if (open_symbol()) {
  1108.       affixes();
  1109.       lastaffixtree = brother;
  1110.       if (close_symbol());
  1111.       else {
  1112.          errmsg("CLOSE symbol");
  1113.          skiptopoint_symbol();
  1114.          rules(rnode);
  1115.          usefullerrmsg = false;
  1116.       }
  1117.       return true;
  1118.    }
  1119.    return false;
  1120. }
  1121.  
  1122.  
  1123. affixes()
  1124. {
  1125.    int             sons;
  1126.    if (flow_symbol()) {
  1127.       terms();
  1128.       sons = brother;
  1129.       if (comma_symbol()) {
  1130.          affixes();
  1131.          newnode(inherited, brother, sons, "(nil)");
  1132.       } else
  1133.          newnode(inherited, nil, sons, "(nil)");
  1134.    } else {
  1135.       terms();
  1136.       sons = brother;
  1137.       if (flow_symbol()) {
  1138.          if (comma_symbol()) {
  1139.             affixes();
  1140.             newnode(derived, brother, sons, "(nil)");
  1141.          } else
  1142.             newnode(derived, nil, sons, "(nil)");
  1143.       } else { 
  1144.          int term;
  1145.          if (comma_symbol()) {
  1146.             affixes();
  1147.             newnode(lattice_affix, brother, sons, "(nil)");
  1148.          } else
  1149.             newnode(lattice_affix, nil, sons, "(nil)");
  1150.          term = SON(brother);;
  1151.          if ((BROTHER(term) != nil ) || (NODENAME(term) != affixnt)) {
  1152.             errmsg("FLOW (>) symbol") ;
  1153.             syntaxerrors += 1;
  1154.          } 
  1155.          if (SON(term) != nil) {
  1156.             errmsg("FLOW (>) symbol") ;
  1157.             syntaxerrors += 1;
  1158.          } 
  1159.       }
  1160.    }
  1161. }
  1162.  
  1163.  
  1164. terms()
  1165. {
  1166.    int             sons;
  1167.    char           *afxnt,
  1168.                   *afxtm;
  1169.    if ((name()) || (dontcare()) ) {
  1170.       afxnt = string;
  1171.       if (plus_symbol()) {
  1172.          terms();
  1173.          newnode(affixnt, brother, nil, afxnt);
  1174.       } else if (fact_symbol()) {
  1175.          factors();
  1176.          newnode(affixnt, brother, nil, afxnt);
  1177.          sons = brother;
  1178.          if (plus_symbol()) {
  1179.             terms();
  1180.             newnode(factor, brother, sons, "(nil)");
  1181.          } else
  1182.             newnode(factor, nil, sons, "(nil)");
  1183.       } else
  1184.          newnode(affixnt, nil, nil, afxnt);
  1185.    } else if (terminal()) {
  1186.       afxtm = string;
  1187.       if (plus_symbol()) {
  1188.          terms();
  1189.          newnode(affixtm, brother, nil, afxtm);
  1190.       } else if (fact_symbol()) {
  1191.          factors();
  1192.          newnode(affixtm, brother, nil, afxtm);
  1193.          sons = brother;
  1194.          if (plus_symbol()) {
  1195.             terms();
  1196.             newnode(factor, brother, sons, "(nil)");
  1197.          } else
  1198.             newnode(factor, nil, sons, "(nil)");
  1199.       } else
  1200.          newnode(affixtm, nil, nil, afxtm);
  1201.    } else {
  1202.       errmsg("TERM") ;
  1203.       if (thischar == '>'||thischar==','||thischar==')'||thischar == '+') 
  1204.            newnode(affixtm, nil, nil, "");
  1205.       else  {
  1206.           skiptopoint_symbol();
  1207.           rules(rnode);
  1208.           usefullerrmsg = false;
  1209.      }
  1210.   }
  1211. }
  1212.  
  1213. char dc_repr[64][4] = {
  1214. "x_a",
  1215. "x_b",
  1216. "x_c",
  1217. "x_d",
  1218. "x_e",
  1219. "x_f",
  1220. "x_g",
  1221. "x_h",
  1222. "x_i",
  1223. "x_j",
  1224. "x_k",
  1225. "x_l",
  1226. "x_m",
  1227. "x_n",
  1228. "x_o",
  1229. "x_p",
  1230. "x_q",
  1231. "x_r",
  1232. "x_s",
  1233. "x_t",
  1234. "x_u",
  1235. "x_v",
  1236. "x_w",
  1237. "x_x",
  1238. "x_y",
  1239. "x_z",
  1240. "x_A",
  1241. "x_B",
  1242. "x_C",
  1243. "x_D",
  1244. "x_E",
  1245. "x_F",
  1246. "x_G",
  1247. "x_H",
  1248. "x_I",
  1249. "x_J",
  1250. "x_K",
  1251. "x_L",
  1252. "x_M",
  1253. "x_N",
  1254. "x_O",
  1255. "x_P",
  1256. "x_Q",
  1257. "x_R",
  1258. "x_S",
  1259. "x_T",
  1260. "x_U",
  1261. "x_V",
  1262. "x_W",
  1263. "x_X",
  1264. "x_Y",
  1265. "x_Z",
  1266. "x_0",
  1267. "x_1",
  1268. "x_2",
  1269. "x_3",
  1270. "x_4",
  1271. "x_5",
  1272. "x_6",
  1273. "x_7",
  1274. "x_8",
  1275. "x_9",
  1276. "X_a",
  1277. "X_b"};
  1278. int dc_cnt = 0;
  1279. dontcare() 
  1280. {
  1281.    if (dontcare_symbol() ) {
  1282.         string = dc_repr[dc_cnt++ &63];
  1283.         return true;
  1284.    }
  1285.    return false;
  1286. }
  1287.  
  1288. factors()
  1289. {
  1290.    char           *afxnt,
  1291.                   *afxtm;
  1292.    if (( name()) || (dontcare())  ) {
  1293.       afxnt = string;
  1294.       if (fact_symbol()) {
  1295.          factors();
  1296.          newnode(affixnt, brother, nil, afxnt);
  1297.       } else
  1298.          newnode(affixnt, nil, nil, afxnt);
  1299.    } else if (terminal()) {
  1300.       afxtm = string;
  1301.       if (fact_symbol()) {
  1302.          factors();
  1303.          newnode(affixtm, brother, nil, afxtm);
  1304.       } else
  1305.          newnode(affixtm, nil, nil, afxtm);
  1306.    } else {
  1307.       errmsg("FACTOR");
  1308.       skiptopoint_symbol();
  1309.       rules(rnode);
  1310.       usefullerrmsg = false;
  1311.    }
  1312. }
  1313.  
  1314.  
  1315. errmsg(msg)
  1316.    char           *msg;
  1317. {
  1318.    if (usefullerrmsg) {
  1319.       if (input_from_partlist)
  1320.           fprintf(stderr, "In %s:\n", cur_part_name);
  1321.       fprintf(stderr, "line %d, char `%c': %s expected\n",
  1322.               line, thischar, msg);
  1323.       syntaxerrors += 1;
  1324.       if (syntaxerrors > 7)
  1325.          exit(12);
  1326.    }
  1327. }
  1328.  
  1329.  
  1330. skiptopoint_symbol()
  1331. {
  1332.    while ((thischar != '.') && (!feof(input)))
  1333.       getnextchar();
  1334.    getnextchar();
  1335. }
  1336.  
  1337.  
  1338. startspecification()
  1339. {
  1340.    if (start_symbol()) {
  1341.       if (startname == NULL)
  1342.          startname = string;
  1343.       else if (startname != string)
  1344.          errmsg("no DOUBLE startspecification");
  1345.       return true;
  1346.    }
  1347.    return false;
  1348. }
  1349.  
  1350. consistentaffixtype(def, app)
  1351. int             def, app;
  1352. {
  1353.    for (;def != nil; def = BROTHER(def), app = BROTHER(app)) 
  1354.       if  (app == nil)
  1355.           return false;
  1356.       else if (NODENAME(def) == NODENAME(app)) {
  1357.       if (NODENAME(def) == lattice_affix)
  1358.        if (DEF(LATTICE_DEF(SON(def))) != DEF(LATTICE_DEF(SON(app)))) {
  1359.       if (input_from_partlist)
  1360.           fprintf(stderr, "In %s:\n", cur_part_name);
  1361.          fprintf(stderr,"%s and %s not in same lattice group\n",
  1362.                 REPR(SON(def)),REPR(SON(app)));
  1363.      
  1364.          return false;
  1365.        }
  1366.       } else return false;
  1367.   
  1368.    if  (app != nil)
  1369.         return false;
  1370.    return true;
  1371. }
  1372.  
  1373. printaffixtype(channel, afxt)
  1374.    FILE           *channel;
  1375.    int             afxt;
  1376. {
  1377.    for (; afxt != nil; afxt = BROTHER(afxt))
  1378.       if (NODENAME(afxt) == derived)
  1379.          fprintf(channel, "d");
  1380.       else if (INHERITED(afxt))
  1381.          fprintf(channel, "i");
  1382.       else 
  1383.          fprintf(channel, "a%d",DEF(LATTICE_DEF(SON(afxt))));
  1384. }
  1385.  
  1386.  
  1387. affixerrmsg(original, bad_copy)
  1388.    int             original,
  1389.                    bad_copy;
  1390. {
  1391.    fprintf(stderr, "Wrong affixtype: (");
  1392.    printaffixtype(stderr, bad_copy);
  1393.    fprintf(stderr, ") expected affixtype: (");
  1394.    printaffixtype(stderr, original);
  1395.    fprintf(stderr, ")\n");
  1396. }
  1397.  
  1398. stddefs()
  1399. {
  1400.    int             i_flag = index_flag;
  1401.    index_flag = false;
  1402.    get_stddefs();
  1403.    input = fopen(stddefs_g, "r");
  1404.    if (input == NULL) {
  1405.       fprintf(stderr, "glammar installation error: %s: No such file\n",
  1406.               stddefs_g);
  1407.       exit(10);
  1408.    }
  1409.    line = 1;
  1410.    getnextchar();
  1411.    rules(rnode);
  1412.    laststdpred = brother;
  1413.    if (hack_flag)  {
  1414.       (void) sprintf(stddefs_g, "%s/glext.g", hack_dir);
  1415.        fclose(input);
  1416.       input = fopen(stddefs_g, "r");
  1417.       if (input == NULL) {
  1418.          fprintf(stderr, "glammar installation error: %s: No such file\n",
  1419.                  stddefs_g);
  1420.          exit(10);
  1421.       }
  1422.       line = 1;
  1423.       getnextchar();
  1424.       rules(rnode);
  1425.       firstnode = brother;
  1426.       getlastnode();
  1427.       BROTHER(lastnode) = laststdpred;
  1428.       laststdpred = firstnode;
  1429.       
  1430.    }
  1431.    fclose(input);
  1432.    index_flag = i_flag;
  1433.    for (cut = laststdpred; (cut != nil)
  1434.          && (!mystrcmp(REPR(cut), "cut")
  1435.              );
  1436.          cut = BROTHER(cut)
  1437.       );
  1438.    if (cut == nil) {
  1439.       fprintf(stderr, "glammar installation error: cut missing\n");
  1440.       exit(12);
  1441.    }
  1442. }
  1443.  
  1444. addpart() { 
  1445.    char *x = thispart;
  1446.    if (hide_flag) {
  1447.       strcat (partptr,".glammar/");
  1448.       partptr += 9;
  1449.    }
  1450.    for (; *x != '\0' ; x++) 
  1451.       *partptr++ = *x;
  1452.    *partptr++ = '.';
  1453.    *partptr++ = 'o';
  1454.    *partptr++ = ' ';
  1455.    *partptr = '\0';
  1456. }
  1457.  
  1458.  
  1459. copy_display() {
  1460.      copy_affixes (defaffixtree);
  1461. }  
  1462.  
  1463. copy_affixes (afx)
  1464. int afx ;
  1465. {
  1466.    int b;
  1467.    if (afx == nil) 
  1468.      return;
  1469.    copy_affixes(BROTHER(afx));
  1470.    b = brother;
  1471.    brother = nil;
  1472.    copy_terms(SON(afx));
  1473.    newnode(NODENAME(afx),b,brother,"");
  1474. }
  1475.  
  1476. copy_terms (term)
  1477. int term ;
  1478. {
  1479.    if (term == nil) 
  1480.      return;
  1481.    copy_terms(BROTHER(term));
  1482.    newnode(NODENAME(term),brother,nil,REPR(term));
  1483. }
  1484.  
  1485.  
  1486. metarule(ruletype)
  1487. int ruletype;
  1488. {
  1489.    int type;
  1490.    char *thisname = string;
  1491.    int b = brother,ln = line;
  1492.    if (ismetarule(&type))
  1493.       switch (type) {
  1494.       case One:
  1495.          if (index_flag) {
  1496.             if (input_from_partlist)
  1497.                fprintf(indexfile, "%s (M), file: `%s' %d\n", thisname, thispart,
  1498.                    line);
  1499.             else
  1500.                fprintf(indexfile, "%s (M), %d\n", thisname, line);
  1501.          }
  1502.          if (ruletype & docompile)
  1503.             newdefnode(meta_prod_rule, lastmetarule, SON(brother), docompile,rulename);
  1504.          else 
  1505.             newnode(meta_prod_rule, lastmetarule, SON(brother), rulename);
  1506.          lastmetarule = brother;
  1507.          break;
  1508.       case OneStar:
  1509.          if (index_flag) {
  1510.             if (input_from_partlist)
  1511.                fprintf(indexfile,"%s (P), file: `%s' %d\n", thisname, thispart,
  1512.                    line);
  1513.             else
  1514.                fprintf(indexfile, "%s (P), %d\n", thisname, line);
  1515.          }
  1516.          if (ruletype & docompile)
  1517.            newdefnode(meta_OneStar , lastmetarule, SON(brother), docompile,rulename);
  1518.          else 
  1519.             newnode(meta_OneStar, lastmetarule, SON(brother), rulename);
  1520.          lastmetarule = brother;
  1521.          break;
  1522.       case Mult:
  1523.          if (index_flag) {
  1524.             if (input_from_partlist)
  1525.                fprintf(indexfile, "%s (S), file: `%s' %d\n", thisname, thispart,
  1526.                    line);
  1527.             else
  1528.                fprintf(indexfile, "%s (S), %d\n", thisname, line);
  1529.          }
  1530. fprintf(stderr, 
  1531. "line %d in metarule `%s':\n\
  1532.      Metaproductions can be implemented using\n\
  1533.      1) Superrules  (ie  superrule :: @ hyperrule).\n\
  1534.          Only applications on *defining* occurrences are recognized.\n\
  1535.      2) Lattices (i.e latticerule :: {} mem1; mem2 . ).\n\
  1536.      See the manual.\n\n",
  1537.                    ln, thisname);
  1538.          syntaxerrors += 1;
  1539.          break;
  1540.       case Super:
  1541.          if (index_flag) {
  1542.             if (input_from_partlist)
  1543.                fprintf(indexfile, "%s (S), file: `%s' %d\n", thisname, thispart,
  1544.                    line);
  1545.             else
  1546.                fprintf(indexfile, "%s (S), %d\n", thisname, line);
  1547.          }
  1548.         if (ruletype & docompile)
  1549.          newdefnode(meta_prod_rule, lastmetarule, brother, docompile,rulename);
  1550.         else 
  1551.          newnode(meta_prod_rule, lastmetarule, brother, rulename);
  1552.        lastmetarule = brother;
  1553.        break;
  1554.  
  1555.       case Lattice:
  1556.          if (index_flag) {
  1557.             if (input_from_partlist)
  1558.                fprintf(indexfile, "%s (A), file: `%s' %d\n", thisname, thispart,
  1559.                    line);
  1560.             else
  1561.                fprintf(indexfile, "%s (A), %d\n", thisname, line);
  1562.          }
  1563.          newnode(0 , nil, brother, rulename);
  1564.          if (first_lattice == nil)
  1565.             first_lattice = brother;
  1566.          else 
  1567.             BROTHER (last_lattice) = brother;
  1568.          last_lattice = brother;
  1569.          break;
  1570.       case Mint:
  1571.          if (index_flag) {
  1572.             if (input_from_partlist)
  1573.                fprintf(indexfile,"%s (P), file: `%s' %d\n", thisname, thispart,
  1574.                    line);
  1575.             else
  1576.                fprintf(indexfile, "%s (P), %d\n", thisname, line);
  1577.          }
  1578.          if (ruletype & docompile)
  1579.            newdefnode(meta_Mint , lastmetarule, brother, docompile,rulename);
  1580.          else 
  1581.             newnode(meta_Mint, lastmetarule, brother, rulename);
  1582.          lastmetarule = brother;
  1583.          break;
  1584.  
  1585.       default :
  1586.          ;
  1587.       }
  1588.    else return false;
  1589.    brother = b;
  1590.    return true;
  1591. }
  1592.  
  1593. ismetarule(type)
  1594. int * type;
  1595. {
  1596.    int l_g;
  1597.    if (define_symbol(&l_g)) {
  1598.       if (superrule())
  1599.          *type = Super;
  1600.       else if (latticerule())
  1601.           *type = Lattice; 
  1602.       else if (numberrule())
  1603.           *type = Mint; 
  1604.       else 
  1605.          *type = abstractionrule();
  1606.       return true; 
  1607.    }
  1608.    return false;
  1609. }
  1610.  
  1611. superrule() {
  1612.    if (super_symbol()) {
  1613.       if (name()) {
  1614.          char           *repr = string;
  1615.          if (!display())   {
  1616.             newnode(affixnt,nil,nil,"x");
  1617.             newnode(derived,nil,brother,"");
  1618.          }
  1619.          else if ((NODENAME(brother) != derived) ||
  1620.              (BROTHER(brother) != nil))
  1621.             errmsg("ONE DERIVED AFFIX");
  1622.          newnode(supernt, nil, brother, repr);
  1623.       } else 
  1624.          errmsg("Super nonterminal");
  1625.       if (!point_symbol()) {
  1626.          skiptopoint_symbol();
  1627.          errmsg("Super metarule");
  1628.       }
  1629.       return true;
  1630.    } else 
  1631.       return false;
  1632. }
  1633.  
  1634. #define DIGIT isdigit(thischar)
  1635. numberrule()
  1636. {
  1637.    if (negate_symbol()) {
  1638.       chartable[charindex++] = '-';
  1639.       if (!DIGIT)  {
  1640.          chartable[charindex++] = '\0';
  1641.          errmsg("NUMBER");
  1642.          skiptopoint_symbol();
  1643.          return true;
  1644.        }
  1645.    }
  1646.    if (pos_symbol());
  1647.    if (!DIGIT) 
  1648.     return false;
  1649.    while (DIGIT) {
  1650.       chartable[charindex++] = thischar;
  1651.       GETnextchar;
  1652.       if (thischar == '\\') {
  1653.          GETnextchar;
  1654.          GETnextchar; /* skip nlcr */
  1655.       }
  1656.    }
  1657.    string = &chartable[prevcharindex];
  1658.    chartable[charindex++] = '\0';
  1659.    prevcharindex = charindex;
  1660.    skiplayout();
  1661.    newnode(affixtm, nil, nil, string);
  1662.    if (!point_symbol()) {
  1663.        skiptopoint_symbol();
  1664.        errmsg("POINT symbol");
  1665.       }
  1666.    return true;
  1667. }
  1668.  
  1669.  
  1670. abstractionrule()
  1671. {
  1672.    int type;  /* One, OneStar, or Mult */
  1673.  
  1674.    /* 
  1675.  * One :: "a" + empty. 
  1676.  * OneStar :: "a" * One.
  1677.  * Mult :: OneStar; One.
  1678.  */
  1679.    type = meta_alts();
  1680.    if (point_symbol());
  1681.    else {
  1682.       errmsg("POINT symbol");
  1683.       skiptopoint_symbol();
  1684.       rules(rnode);
  1685.       exit(1);
  1686.    }
  1687.    return type;
  1688. }
  1689.  
  1690.  
  1691. meta_alts()
  1692. {
  1693.    int             sons, type  = One;
  1694.    brother = nil;
  1695.    type = meta_terms();
  1696.    sons = brother;
  1697.    if (goon_symbol()) {
  1698.         type = Mult;
  1699.         meta_alts();
  1700.         newnode(meta_alt, brother, sons, "meta_alt");
  1701.   }
  1702.   else
  1703.          newnode(meta_alt, nil, sons, "meta_alt");
  1704.    return type;
  1705. }
  1706.  
  1707. meta_terms()
  1708. {
  1709.    int             sons, type  = One;
  1710.    char           *afxnt, *afxtm;
  1711.    if (name()) {
  1712.       afxnt = string;
  1713.       if (plus_symbol()) {
  1714.          type = meta_terms();
  1715.          newnode(affixnt, brother, nil, afxnt);
  1716.       } else if (fact_symbol()) {
  1717.          type = OneStar;
  1718.          meta_factors();
  1719.          newnode(affixnt, brother, nil, afxnt);
  1720.          sons = brother;
  1721.          if (plus_symbol()) {
  1722.             type = meta_terms();
  1723.             newnode(factor, brother, sons, "(nil)");
  1724.          } else
  1725.             newnode(factor, nil, sons, "(nil)");
  1726.       } else
  1727.          newnode(affixnt, nil, nil, afxnt);
  1728.    } else if (terminal()) {
  1729.       afxtm = string;
  1730.       if (plus_symbol()) {
  1731.          type = meta_terms();
  1732.          newnode(affixtm, brother, nil, afxtm);
  1733.       } else if (fact_symbol()) {
  1734.          type = OneStar;
  1735.          meta_factors();
  1736.          newnode(affixtm, brother, nil, afxtm);
  1737.          sons = brother;
  1738.          if (plus_symbol()) {
  1739.             meta_terms();
  1740.             newnode(factor, brother, sons, "(nil)");
  1741.          } else
  1742.             newnode(factor, nil, sons, "(nil)");
  1743.       } else
  1744.          newnode(affixtm, nil, nil, afxtm);
  1745.    } else if (set()) {
  1746.       type = Mult;
  1747.       if (plus_symbol()) {
  1748.          int lastst = lastsettype;
  1749.          char * repr = string;
  1750.          meta_terms();
  1751.          newnode(cnode | lastst, brother, nil, repr);
  1752.       } else newnode(cnode | lastsettype, nil, nil, string);
  1753.    } else 
  1754.          newnode(affixtm, nil, nil, "");
  1755.    return type;
  1756. }
  1757.  
  1758. meta_factors()
  1759. {
  1760.    char           *afxnt,
  1761.    *afxtm;
  1762.    if (name()) {
  1763.       afxnt = string;
  1764.       if (fact_symbol()) {
  1765.          meta_factors();
  1766.          newnode(affixnt, brother, nil, afxnt);
  1767.       } else
  1768.          newnode(affixnt, nil, nil, afxnt);
  1769.    } else if (terminal()) {
  1770.       afxtm = string;
  1771.       if (fact_symbol()) {
  1772.          meta_factors();
  1773.          newnode(affixtm, brother, nil, afxtm);
  1774.       } else
  1775.          newnode(affixtm, nil, nil, afxtm);
  1776.    } else {
  1777.       errmsg("FACTOR");
  1778.       skiptopoint_symbol();
  1779.       rules(rnode);
  1780.       usefullerrmsg = false;
  1781.    }
  1782. }
  1783.  
  1784. latticerule()
  1785. {
  1786.    if (lattice_symbol()) {
  1787.       brother = nil;
  1788.       lattice_mems();
  1789.       if (point_symbol());
  1790.       else {
  1791.          errmsg("POINT symbol");
  1792.          skiptopoint_symbol();
  1793.          rules(rnode);
  1794.          exit(1);
  1795.       }
  1796.       return true;
  1797.    }
  1798.    return false;
  1799. }
  1800.  
  1801. lattice_mems()
  1802. {
  1803.    char           *afxnt,
  1804.    *afxtm;
  1805.    if (name()) {
  1806.       afxnt = string;
  1807.       if (goon_symbol()) {
  1808.          lattice_mems();
  1809.          newnode(0, brother, nil, afxnt);
  1810.       } else
  1811.          newnode(0, nil, nil, afxnt);
  1812.    } else {
  1813.       errmsg("LATTICE MEMBER");
  1814.       skiptopoint_symbol();
  1815.       rules(rnode);
  1816.       exit(1);
  1817.    }
  1818. }
  1819.